package com.system.framework.aspect;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author wq
 * @date 2022/10/9 11:15
 */
@Component
@Aspect
@Slf4j
public class RequestParameterAop {


    @Value("${token.header}")
    private String header;


    @Around("@within(org.springframework.web.bind.annotation.RestController)" +
            "||@within(org.springframework.stereotype.Controller)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader(header);
        String requestUri = request.getRequestURI();
        StopWatch stopWatch = StopWatch.createStarted();
        Object result = joinPoint.proceed(joinPoint.getArgs());
        stopWatch.stop();
        log.info("\n{ \n请求地址:【{}】 \n请求参数:【{}】  \n请求令牌:【{}】  \n请求方式:【{}】 \n请求类方法:{} \n请求耗时:【{}】毫秒 \n}",
                requestUri,
                JSONObject.toJSONString(filterArgs(joinPoint.getArgs())),
                token,
                request.getMethod(),
                joinPoint.getSignature(),
                stopWatch.getTime(TimeUnit.MILLISECONDS));
        return result;
    }

    private Object filterArgs(Object[] objects) {
        return Arrays.stream(objects).filter(obj -> !(obj instanceof MultipartFile)
                && !(obj instanceof HttpServletResponse)
                && !(obj instanceof HttpServletRequest)).collect(Collectors.toList());
    }

}
